﻿using System;
using System.Collections.Generic;
using System.Data;
using MedicService.Domain;
using MedicService.Server.Factory.Directory;
using MedicService.Server.Factory.Directory.Simple;
using MedicService.Server.Factory.Generic;

namespace MedicService.Server.Factory {
    public class DoctorFactory : EntityFactory<Doctor> {

        private readonly DegreeFactory degreeFactory = new DegreeFactory();
        private readonly AcademicTitleFactory academicTitleFactory = new AcademicTitleFactory();
        private readonly RegionFactory regionFactory = new RegionFactory();
        private readonly LocalityFactory localityFactory = new LocalityFactory();
        private readonly InstitutionFactory institutionFactory = new InstitutionFactory();
        private readonly InstitutionTypeFactory institutionTypeFactory = new InstitutionTypeFactory();
        private readonly JobFactory jobFactory = new JobFactory();
        private readonly ClassFactory classFactory = new ClassFactory();
        private readonly SpecialityFactory specialityFactory = new SpecialityFactory();
        private readonly OrderFactory orderFactory = new OrderFactory();
        private readonly GroupExpFactory groupExpFactory = new GroupExpFactory();

        public DoctorFactory(): base("Doctor", "Surname"){}

        public DoctorFactory(int year) : base("Doctor", "Surname", " RegstrationDate >= " + Date(new DateTime(year, 1, 1)) + " AND RegstrationDate < " + Date(new DateTime(year+1, 1, 1))) { }

        public DoctorFactory(bool init, int year): this(year) {
            if (init) {
                initMaps();
            }
        }

        public DoctorFactory(bool init, string surname, string name, string patronymic, int bornYear)
            : base("Doctor", "NumberInOrder", " Surname="+Nullable(surname)+" AND Name="+ Nullable(name)+ " AND Patronymic="+Nullable(patronymic) + " AND Data="+Nullable(bornYear)) {
            if (init) {
                initMaps();
            }
        }

        public DoctorFactory(bool init)
            : this() {
            if (init) {
                initMaps();
            }
        }

        private void initMaps() {
            degreeFactory.InitMap();
            academicTitleFactory.InitMap();
            regionFactory.InitMap();
            localityFactory.InitMap();
            institutionFactory.InitMap();
            institutionTypeFactory.InitMap();
            jobFactory.InitMap();
            classFactory.InitMap();
            specialityFactory.InitMap();
            orderFactory.InitMap();
            groupExpFactory.InitMap();
        }

        protected override Doctor CreateEntity() {
            return new Doctor();
        }

        protected override string GetInsertQuery(Doctor entity) {
            string q = "INSERT INTO [Doctor]" +
            "           ([NumberInOrder]	" +
            "           ,[Surname]			" +
            "           ,[Name]				" +
            "           ,[Patronymic]		" +
            "           ,[Data]				" +
            "           ,[DegreeId]			" +
            "           ,[AcademicTitleId]	" +
            "           ,[sex]				" +
            "           ,[address]			" +
            "           ,[PhoneHome]		" +
            "           ,[PhoneMobile]		" +
            "           ,[RegionId]			" +
            "           ,[LocalityId]		" +
            "           ,[InstitutionId]	" +
            "           ,[InstitutionTypeId]" +
            "           ,[belonging]		" +
            "           ,[InstitutionAddress]" +
            "           ,[InstitutionPhone]	" +
            "           ,[jobid]			" +
            "           ,[OldSpecialityId]	" +
            "           ,[OldClassId]		" +
            "           ,[experience]		" +
            "           ,[NewSpecialityId]	" +
            "           ,[NewClassId]		" +
            "           ,[Assign]		" +
            "           ,[GroupExpId]		" +
            "           ,[OrderId]			" +
            "           ,[RegstrationDate]	" +
            "           ,[ContractNumber]	" +
            "           ,[Reject]	        " +
            "           ,[jobId2])			" +
            "     VALUES(					" +
            "          "+Nullable(entity.NumberInOrder)+"    ," +
            "          "+Nullable(entity.Surname)+"         ," +
            "          "+Nullable(entity.Name)+"            ," +
            "          "+Nullable(entity.Patronymic)+"      ," +
            "          "+Nullable(entity.Data)+"            ," +
            "          "+Nullable(entity.Degree)+"        ," +
            "          "+Nullable(entity.AcademicTitle)+" ," +
            "          "+Nullable(entity.Sex)+"              ," +
            "          "+Nullable(entity.Address)+"         ," +
            "          "+Nullable(entity.PhoneHome)+"       ," +
            "          "+Nullable(entity.PhoneMobile)+"     ," +
            "          "+Nullable(entity.Region)+"        ," +
            "          "+Nullable(entity.Locality)+"      ," +
            "          "+Nullable(entity.Institution)+"   ," +
            "          "+Nullable(entity.InstitutionType)+"," +
            "          "+Nullable(entity.Belonging)+"        ," +
            "          "+Nullable(entity.InstitutionAddress)+"," +
            "          "+Nullable(entity.InstitutionPhone)+"," +
            "          "+Nullable(entity.Job)+"           ," +
            "          "+Nullable(entity.OldSpeciality)+" ," +
            "          "+Nullable(entity.OldClass)+"      ," +
            "          "+Nullable(entity.Experience)+"      ," +
            "          "+Nullable(entity.NewSpeciality)+" ," +
            "          "+Nullable(entity.NewClass)+"      ," +
            "          " + Nullable(entity.Assign) + "     ," +
            "          "+Nullable(entity.GroupExp)+"      ," +
            "          "+Nullable(entity.Order)+"         ," +
            "          "+Date(entity.RegstrationDate)+" ," +
            "          "+Nullable(entity.ContractNumber)+"	," +
            "          " + Nullable(entity.Reject) + "	," +
            "          " + Nullable(entity.Job2) + ");        " +
            "            ";
            return q;
        }

        protected override string GetUpdateQuery(Doctor entity) {
            string q = "UPDATE [Doctor]	" +
            "   SET [NumberInOrder] = " + Nullable(entity.NumberInOrder)+
            "      ,[Surname] = " + Nullable(entity.Surname) +
            "      ,[Name] = " + Nullable(entity.Name) +
            "      ,[Patronymic] = " + Nullable(entity.Patronymic) +
            "      ,[Data] = " + Nullable(entity.Data) +
            "      ,[DegreeId] = " + Nullable(entity.Degree) +
            "      ,[AcademicTitleId] = " + Nullable(entity.AcademicTitle.Id) +
            "      ,[sex] = " + Nullable(entity.Sex) +
            "      ,[address] =  " + Nullable(entity.Address) +
            "      ,[PhoneHome] =  " + Nullable(entity.PhoneHome) +
            "      ,[PhoneMobile] =  " + Nullable(entity.PhoneMobile) +
            "      ,[RegionId] = " + Nullable(entity.Region.Id) +
            "      ,[LocalityId] = " + Nullable(entity.Locality.Id) +
            "      ,[InstitutionId] = " + Nullable(entity.Institution.Id) +
            "      ,[InstitutionTypeId] = " + Nullable(entity.InstitutionType.Id) +
            "      ,[belonging] =  " + Nullable(entity.Belonging) +
            "      ,[InstitutionAddress] =  " + Nullable(entity.InstitutionAddress) +
            "      ,[InstitutionPhone] =  " + Nullable(entity.InstitutionPhone) +
            "      ,[jobid] = " + Nullable(entity.Job.Id) +
            "      ,[OldSpecialityId] = " + Nullable(entity.OldSpeciality.Id) +
            "      ,[OldClassId] = " + Nullable(entity.OldClass.Id) +
            "      ,[experience] =  " + Nullable(entity.Experience) +
            "      ,[NewSpecialityId] = " + Nullable(entity.NewSpeciality.Id) +
            "      ,[NewClassId] = " + Nullable(entity.NewClass.Id) +
            "      ,[Assign] = " + Nullable(entity.Assign) +
            "      ,[GroupExpId] = " + Nullable(entity.GroupExp.Id) +
            "      ,[OrderId] = " + Nullable(entity.Order.Id) +
            "      ,[RegstrationDate] = " + Date(entity.RegstrationDate) +
            "      ,[ContractNumber] = " + Nullable(entity.ContractNumber) +
            "      ,[jobId2] = " + Nullable(entity.Job2) +
            "      ,[Reject] = " + Nullable(entity.Reject) +
            " WHERE id = " + entity.Id + ";";
            return q;
        }

        //private static string Date(DateTime dateTime) {
        //    return "'" + dateTime.Year + "-" + dateTime.Month + "-" + dateTime.Day + "'";
        //}


        //private static object Nullable(Entity item) {
        //    if (item == null || item.Id == 0) {
        //        return "NULL";
        //    } else {
        //        return "'" + item.Id + "'";
        //    }
        //}

        //private static string Nullable(object o) {
        //    if (o == null) {
        //        return "NULL";
        //    }else {
        //        return "'" + o + "'";
        //    }
        //}
        
        protected override void FillEntity(Doctor entity, DataRow myDataRow) {
            base.FillEntity(entity, myDataRow);
            entity.AcademicTitle = academicTitleFactory.Load(myDataRow["AcademicTitleId"]);
            entity.Address =  myDataRow["address"] as string;
            entity.Belonging = myDataRow["belonging"] as int?;
            //entity.Confirmation = myDataRow["Confirmation"] as int?;
            if (Convert.IsDBNull(myDataRow["Assign"]))
            {
                entity.Assign = null;
            }
            else
            {
                entity.Assign = Convert.ToInt32("" + myDataRow["Assign"]);
            }
            entity.ContractNumber = myDataRow["ContractNumber"] as int?;
            entity.Data =  myDataRow["Data"] as string;
            entity.Degree = degreeFactory.Load(myDataRow["DegreeId"]);
            entity.Experience =  myDataRow["experience"] as string;
            entity.GroupExp = groupExpFactory.Load(myDataRow["GroupExpId"]);
            entity.Id = (int) myDataRow["id"];
            entity.Institution = institutionFactory.Load(myDataRow["InstitutionId"]);
            entity.InstitutionAddress = myDataRow["InstitutionAddress"] as string;
            entity.InstitutionPhone = myDataRow["InstitutionPhone"] as string;
            entity.InstitutionType = institutionTypeFactory.Load(myDataRow["InstitutionTypeId"]);
            entity.Job = jobFactory.Load(myDataRow["jobid"]);
            entity.Job2 = jobFactory.Load(myDataRow["jobid2"]);
            entity.Locality = localityFactory.Load(myDataRow["LocalityId"]);
            entity.Name =  myDataRow["Name"] as string;
            entity.NewClass = classFactory.Load(myDataRow["NewClassId"]);
            entity.NewSpeciality = specialityFactory.Load(myDataRow["NewSpecialityId"]);
            if (Convert.IsDBNull(myDataRow["NumberInOrder"])) {
                entity.NumberInOrder = null;
            } else {
                entity.NumberInOrder = Convert.ToInt32("" + myDataRow["NumberInOrder"]);
            }
            entity.OldClass = classFactory.Load(myDataRow["OldClassId"]);
            entity.OldSpeciality = specialityFactory.Load(myDataRow["OldSpecialityId"]);
            entity.Order = orderFactory.Load(myDataRow["OrderId"]);
            entity.Patronymic =  myDataRow["Patronymic"] as string;
            entity.PhoneHome =  myDataRow["PhoneHome"] as string;
            entity.PhoneMobile =  myDataRow["PhoneMobile"] as string;
            entity.Region = regionFactory.Load(myDataRow["RegionId"]);
            entity.RegstrationDate = (DateTime) myDataRow["RegstrationDate"];
            entity.Reject = myDataRow["Reject"] as int?;
            entity.Sex = myDataRow["sex"] as int?;
            entity.Surname =  myDataRow["Surname"] as string;
        }

        private static int ToInt(object obj) {
            string s = obj.ToString();
            return s.Length > 0 ? int.Parse(s) : 0;
        }

        internal List<Doctor> GetListByOrder(Order order) {
            var entities = new List<Doctor>();
            var dataTable = DatabaseConnector.GetData(TableName, "NumberInOrder", "OrderId=" + order.Id);
            foreach (DataRow myDataRow in dataTable.Rows) {
                var entity = CreateEntity();
                FillEntity(entity, myDataRow);
                entities.Add(entity);
            }
            return entities;
        }
    
        internal List<Doctor> GetListNotInOrder() {
            var entities = new List<Doctor>();
            var dataTable = DatabaseConnector.GetData(TableName, OrderBy, "OrderId IS NULL");
            foreach (DataRow myDataRow in dataTable.Rows) {
                var entity = CreateEntity();
                FillEntity(entity, myDataRow);
                entities.Add(entity);
            }
            return entities;
        }

        public int GenMaxNumber() {
            int contractNumber = 0;
            DataTable dataTable = DatabaseConnector.GetData(TableName, "ContractNumber DESC", null, 1);
            foreach (DataRow myDataRow in dataTable.Rows) {
                var entity = CreateEntity();
                FillEntity(entity, myDataRow);
                contractNumber = (int)(entity.ContractNumber ?? 0);
            }
            return contractNumber;
        }
    }
}
